package gramaticaPrecedencia;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

import com.thoughtworks.xstream.XStream;

import simbolo.Par;
import simbolo.Simbolo;

public class Tabla {
	
	private boolean tablaCorrecta= true;
	private Simbolo coord_errorX= null;
	private Simbolo coord_errorY= null;
	//private ArrayList<ArrayList<Character>> tabla;
	private ArrayList<Simbolo> coordenadas;
	private Character [] [] tabla;
	
	public Tabla(Collection<Simbolo> simbolos){
		int largo = simbolos.size();
		//Armar tabla
		tabla= new Character[largo][largo];
		
		//Armar coordenadas
		coordenadas= new ArrayList<Simbolo>(largo);
		coordenadas.addAll(simbolos);
	}
	public boolean Serializar(String path){
    	
		boolean escrituraExitosa= true;
		if(path==null){
    		//Valor por defecto
    		path = new String("Tabla.xml");
    	}
        XStream xstream = new XStream();

        String tablaXml = xstream.toXML(this);

        try {
            BufferedWriter tablaArchivo = new BufferedWriter(new FileWriter(path));
            tablaArchivo.write(tablaXml);
            tablaArchivo.close();
        } catch (IOException e) {
        	escrituraExitosa = false;
        	System.out.println("Error al escribir el archivo en el path: "+ path);
        }
        
        return escrituraExitosa;
	}
	public void addRelacion(Simbolo x, Simbolo y, Character relacion) throws ConflictoTabla{
		
		assert(relacion.equals('>') || relacion.equals('<') || relacion.equals('='));
		
		int ubi_x= coordenadas.indexOf(x);
		int ubi_y= coordenadas.indexOf(y);
		//Veo si habia una relacion distinta a la que hay que agregar
		if (getTabla()[ubi_x][ubi_y] == null){
			getTabla()[ubi_x][ubi_y] = relacion;
		}
		//si hay algo me fijo que no sea distinto q lo que pensaba poner
		else if(getTabla()[ubi_x][ubi_y].compareTo(relacion)!=0){
			tablaCorrecta= false;
			setCoord_errorX(x);
			setCoord_errorY(y);
			throw new ConflictoTabla(new Par(x,y), this, getTabla()[ubi_x][ubi_y], relacion);
		}	
	}
	
	public Character getRelacion(Simbolo x, Simbolo y){
		assert (coordenadas.indexOf(x) != -1 && coordenadas.indexOf(y) != -1);
		
		int ubi_x= coordenadas.indexOf(x);
		int ubi_y= coordenadas.indexOf(y);
		
		return getTabla()[ubi_x][ubi_y];
		
	}
	
	public String toString(){
		String laTabla= new String("  ");
		//Primero muestro el head de la tabla
		for (int i=0; i< getCoordenadas().size(); i++){
			laTabla = laTabla.concat("  " + getCoordenadas().get(i).toString() + "  ");
		}
		int derechaDeLaTabla=0;
		for (int x= 0; x< getTabla().length; x++ ){
			// A cada itearacion de x agrego el campo que mostrar'a.
			laTabla = laTabla.concat("\n");
			laTabla = laTabla.concat(getCoordenadas().get(derechaDeLaTabla).toString() + " ");
			derechaDeLaTabla++;
			for (int y=0; y< getTabla().length; y++){
				if (getTabla()[x][y]!=null){ 
					laTabla = laTabla.concat("  " + getTabla()[x][y].toString() + "  ");
				}else {
					laTabla = laTabla.concat("null ");
				}
			}
		}
		return laTabla;
	}
	
	//Getters y Setter
	public ArrayList<Simbolo> getCoordenadas() {
		return coordenadas;
	}
	public void setCoordenadas(ArrayList<Simbolo> coordenadas) {
		this.coordenadas = coordenadas;
	}
	
	public boolean isTablaCorrecta() {
		return tablaCorrecta;
	}
	public void setTablaCorrecta(boolean tablaCorrecta) {
		this.tablaCorrecta = tablaCorrecta;
	}
	public void setTabla(Character[][] tabla) {
		this.tabla = tabla;
	}
	public Character[][] getTabla() {
		return tabla;
	}
	public Simbolo getCoord_errorX() {
		return coord_errorX;
	}
	public void setCoord_errorX(Simbolo coord_errorX) {
		this.coord_errorX = coord_errorX;
	}
	public Simbolo getCoord_errorY() {
		return coord_errorY;
	}
	public void setCoord_errorY(Simbolo coord_errorY) {
		this.coord_errorY = coord_errorY;
	}
}
